import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'

// 请求配置接口
interface RequestConfig extends AxiosRequestConfig {
  showLoading?: boolean
  showError?: boolean
}

// 响应数据格式
interface ResponseData<T = any> {
  code: number
  data: T
  message: string
  success: boolean
}

class Request {
  private instance: AxiosInstance
  private loading = false

  constructor(config: AxiosRequestConfig) {
    this.instance = axios.create(config)
    this.setupInterceptors()
  }

  private setupInterceptors() {
    // 请求拦截器
    this.instance.interceptors.request.use(
      (config) => {
        // 添加token
        const token = uni.getStorageSync('token')
        if (token) {
          config.headers.Authorization = `Bearer ${token}`
        }

        // 显示加载提示
        if ((config as RequestConfig).showLoading !== false) {
          this.showLoading()
        }

        return config
      },
      (error) => {
        this.hideLoading()
        return Promise.reject(error)
      }
    )

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse<ResponseData>) => {
        this.hideLoading()

        const { data } = response
        
        // 请求成功
        if (data.success || data.code === 200) {
          return data as any
        }

        // 业务错误
        if ((response.config as RequestConfig).showError !== false) {
          this.showError(data.message || '请求失败')
        }

        return Promise.reject(new Error(data.message || '请求失败'))
      },
      (error) => {
        this.hideLoading()

        let message = '网络异常，请稍后重试'
        
        if (error.response) {
          const { status, data } = error.response
          
          switch (status) {
            case 401:
              message = '未授权，请重新登录'
              // 清除token并跳转到登录页
              uni.removeStorageSync('token')
              uni.reLaunch({
                url: '/pages/login/login'
              })
              break
            case 403:
              message = '拒绝访问'
              break
            case 404:
              message = '请求的资源不存在'
              break
            case 500:
              message = '服务器内部错误'
              break
            default:
              message = data?.message || `请求失败 (${status})`
          }
        } else if (error.code === 'NETWORK_ERROR') {
          message = '网络连接失败'
        } else if (error.code === 'TIMEOUT') {
          message = '请求超时'
        }

        if ((error.config as RequestConfig)?.showError !== false) {
          this.showError(message)
        }

        return Promise.reject(error)
      }
    )
  }

  private showLoading() {
    if (!this.loading) {
      this.loading = true
      uni.showLoading({
        title: '加载中...',
        mask: true
      })
    }
  }

  private hideLoading() {
    if (this.loading) {
      this.loading = false
      uni.hideLoading()
    }
  }

  private showError(message: string) {
    uni.showToast({
      title: message,
      icon: 'none',
      duration: 2000
    })
  }

  // GET 请求
  get<T = any>(url: string, config?: RequestConfig): Promise<ResponseData<T>> {
    return this.instance.get(url, config)
  }

  // POST 请求
  post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ResponseData<T>> {
    return this.instance.post(url, data, config)
  }

  // PUT 请求
  put<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ResponseData<T>> {
    return this.instance.put(url, data, config)
  }

  // DELETE 请求
  delete<T = any>(url: string, config?: RequestConfig): Promise<ResponseData<T>> {
    return this.instance.delete(url, config)
  }

  // 上传文件
  upload<T = any>(url: string, filePath: string, config?: RequestConfig): Promise<ResponseData<T>> {
    return new Promise((resolve, reject) => {
      const token = uni.getStorageSync('token')
      
      if (config?.showLoading !== false) {
        this.showLoading()
      }

      uni.uploadFile({
        url: this.instance.defaults.baseURL + url,
        filePath,
        name: 'file',
        header: {
          Authorization: token ? `Bearer ${token}` : '',
          ...config?.headers
        },
        success: (res: any) => {
          this.hideLoading()
          try {
            const data = JSON.parse(res.data)
            if (data.success || data.code === 200) {
              resolve(data)
            } else {
              if (config?.showError !== false) {
                this.showError(data.message || '上传失败')
              }
              reject(new Error(data.message || '上传失败'))
            }
          } catch (error) {
            if (config?.showError !== false) {
              this.showError('上传失败')
            }
            reject(error)
          }
        },
        fail: (error: any) => {
          this.hideLoading()
          if (config?.showError !== false) {
            this.showError('上传失败')
          }
          reject(error)
        }
      })
    })
  }
}

// 创建请求实例
const request = new Request({
  baseURL: 'https://api.example.com',
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json'
  }
})

export default request
export type { RequestConfig, ResponseData }
export { Request }
